package game_services

import (
	"errors"
	"fmt"
	"log"
	"longmen/server/config/global"
	_const "longmen/server/pkg/common/helper/const"
	"longmen/server/pkg/common/helper/timehelper"
	"longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql/db_live"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_main"
	"longmen/server/pkg/db/redis/cache"
	pb "longmen/server/pkg/protobuf"
	"time"

	"gorm.io/gorm"
)

const DailyChance = 2
const DAILY_CHANCE = "DAILY_CHANCE_%d_%s"
const RESET_STAGE = "RESET_STAGE_%d"
const RESET_COUNTDOWN = 7

// return chance, max_stage, user curreng_stage
func Signin(userID int) (int, int, int, int, []*pb.Stage) {
	maxStage, currentStage := getStage(userID)
	first, countdown := checkCountdown(userID)
	if first {
		currentStage = 0
	}
	return getChange(userID), maxStage, currentStage, countdown, GetStages()
}

func SignStage(userID int) (*pb.SigninStageResp, error) {
	chance := getChange(userID)
	if chance == 0 {
		return nil, errors.New("今日游戏次数已用完")
	}

	var reward *pb.SigninReward
	var randStep int
	var stage int

	for { // 实物跳过重抽
		seed := util.MaxMinRand(1, 10)
		if seed <= 2 {
			randStep = 1
		} else {
			randStep = util.MaxMinRand(2, 6) // 目前是骰子1-6
		}

		maxStage, currentStage := getStage(userID)
		stage = randStep + currentStage
		if randStep+currentStage > maxStage {
			stage = maxStage
		}
		reward = stageReward(stage)

		log.Println("randStep:", randStep)
		log.Println("stage:", stage)

		if reward.Type != 2 || stage == maxStage {
			break
		}
	}

	//1虚拟直播道具,2实物,3机会次数,4,前进或后退步数,5钻石，6宝石
	// 如果是虚拟道具发放到背包
	if reward.Type == 1 {
	}

	if reward.Type == 3 {
		chance = chance + int(reward.Quantity)
		setChance(userID, chance)
	}

	if reward.Type == 5 {
		tx := global.GetR().Begin()
		userProfit := &models_main.UserProfit{
			Uid:         userID,
			FUid:        0, //system
			ConsumeType: _const.PROFIT_LOTTERY_AWARD,
			Type:        _const.TYPE_PROFIT,
			CoinCount:   int(reward.Quantity * 100),
			Content:     util.GetConsumeName(25),
			CreateTime:  time.Now(),
			Resid:       0,
			Count:       0,
			CoinType:    2,
			OrderNo:     util.GenOrderId("SIG", 1),
			Liveid:      0,
		}
		_, _, err := db_main.UpdateAmountByTx(userID, int(reward.Quantity*100), _const.CoinDiamond, tx, _const.WALLET_BALANCE_SHOW, []*models_main.UserProfit{userProfit})
		if err != nil {
			global.Log.Errorf("SignStage UpdateAmount err#1:", err)
			return nil, err
		}
		// 更新缓存
		userCacheKey := fmt.Sprintf(_const.REDIS_USER_FULL_INFO, userID)
		global.GetRds().Del(userCacheKey)
		tx.Commit()
	}

	if reward.Type == 6 {
		tx := global.GetR().Begin()
		userProfit := &models_main.UserProfit{
			Uid:         userID,
			FUid:        0, //system
			ConsumeType: _const.PROFIT_LOTTERY_AWARD,
			Type:        _const.TYPE_PROFIT,
			CoinCount:   int(reward.Quantity * 100),
			Content:     util.GetConsumeName(25),
			CreateTime:  time.Now(),
			Resid:       0,
			Count:       0,
			CoinType:    1,
			OrderNo:     util.GenOrderId("SIG", 1),
			Liveid:      0,
		}
		_, _, err := db_main.UpdateAmountByTx(userID, int(reward.Quantity*100), _const.CoinGold, tx, _const.WALLET_BALANCE_SHOW, []*models_main.UserProfit{userProfit})
		if err != nil {
			global.Log.Errorf("SignStage UpdateAmount err#2:", err)
			return nil, err
		}
		// 更新缓存
		userCacheKey := fmt.Sprintf(_const.REDIS_USER_FULL_INFO, userID)
		global.GetRds().Del(userCacheKey)
		tx.Commit()
	}

	if reward.Type == 7 {
		err := global.GetR().Model(&models_main.User{}).Where("id=?", userID).Update("point", gorm.Expr("point+?", reward.Quantity)).Error
		if err != nil {
			global.Log.Errorf("SignStage UpdatePoint err:", err)
			return nil, err
		}
		// 更新缓存
		userCacheKey := fmt.Sprintf(_const.REDIS_USER_FULL_INFO, userID)
		global.GetRds().Del(userCacheKey)
	}

	if reward.Type == 105 {
		if err := db_live.ProvideTicket([]int64{int64(userID)}, int(reward.Quantity), 3); err != nil {
			global.Log.Infof("ProvideTicket error: %v", err)
			return nil, err
		}

	}

	setChance(userID, chance-1)

	// 第一次开始活动之后开始记录重置倒计时
	first, _ := checkCountdown(userID)
	if first {
		st, _ := timehelper.INaDay2Unix("")
		global.GetRds().Set(fmt.Sprintf(RESET_STAGE, userID), st, RESET_COUNTDOWN*24*3600*time.Second)
	}

	// 再来一次的可能性
	more_chance := 0
	if util.MaxMinRand(1, 10) == 5 {
		more_chance = 1
		setChance(userID, getChange(userID)+1)
	}

	// 用户平台来源
	user, _ := cache.GetUserFullInfo(userID)
	// 记录历史
	var res = models_main.SigninHistory{
		PropsID:    int(reward.PropsId),
		UserID:     userID,
		Nickname:   cache.GetUserNickNameById(userID),
		Stage:      stage,
		SigninID:   int(reward.Id),
		Name:       reward.Name,
		Quantity:   int(reward.Quantity),
		Thumb:      reward.Thumb,
		Type:       reward.Type,
		Rank:       reward.Rank,
		MoreChance: int32(more_chance),
		Platform:   int32(user.LoginPlatform),
		CreatedAt:  time.Now(),
	}

	err := global.GetR().Model(&models_main.SigninHistory{}).Create(&res).Error
	if err != nil {
		global.Log.Errorf("stageReward err#1:", err)
	}

	return &pb.SigninStageResp{
		Step:         int64(randStep),
		Reward:       reward,
		MoreChance:   int32(more_chance),
		CurrentStage: int32(stage),
	}, nil
}

func SigninHistory(userID int) []*pb.SigninHistory {
	var ret []*pb.SigninHistory
	err := global.GetR().Model(&models_main.SigninHistory{}).Where("user_id", userID).Order("id desc").Limit(20).Find(&ret).Error
	if err != nil {
		global.Log.Errorf("SigninHistory err:", err)
	}
	// 临时处理类似时间格式 2024-02-16T18:40:49+08:00
	for idx, v := range ret {
		t, _ := time.ParseInLocation(time.RFC3339, v.CreatedAt, time.Now().Location())
		ret[idx].CreatedAt = t.Format("2006-01-02 15:04:05")
	}

	return ret
}

func getStage(userID int) (int, int) {
	var maxStage int
	var currentStage int
	var err error

	err = global.GetR().Model(&models_main.Signin{}).Order("stage desc").Limit(1).Pluck("stage", &maxStage).Error
	if err != nil {
		global.Log.Errorf("Signin err#2:", err)
	}

	first, _ := checkCountdown(userID)
	if first {
		currentStage = 0
		return maxStage, currentStage
	}

	err = global.GetR().Model(&models_main.SigninHistory{}).Where("user_id=?", userID).Order("id desc").Limit(1).Pluck("stage", &currentStage).Error
	if err != nil {
		global.Log.Errorf("Signin err#1:", err)
	}

	// 如果跑完一圈 重置当前关卡为起始0
	if maxStage == currentStage {
		currentStage = 0
	}

	return maxStage, currentStage
}

func GetStages() []*pb.Stage {
	var stages []*pb.Stage
	err := global.GetR().Model(&models_main.Signin{}).Order("stage").Find(&stages).Error
	if err != nil {
		global.Log.Errorf("getStages err:", err)
	}

	return stages
}

func getChange(userID int) int {
	var chance = 0
	check, _ := global.GetRds().Exists(fmt.Sprintf(DAILY_CHANCE, userID, time.Now().Format("2006-01-02"))).Result()
	if check == 0 {
		chance = DailyChance
	} else {
		chance, _ = global.GetRds().Get(fmt.Sprintf(DAILY_CHANCE, userID, time.Now().Format("2006-01-02"))).Int()
	}

	return chance
}

func setChance(userID int, chance int) {
	global.GetRds().Set(fmt.Sprintf(DAILY_CHANCE, userID, time.Now().Format("2006-01-02")), chance, time.Hour*24)
}

func stageReward(stage int) *pb.SigninReward {
	var ret *pb.SigninReward
	err := global.GetR().Model(&models_main.Signin{}).Where("stage=?", stage).First(&ret).Error
	if err != nil {
		global.Log.Errorf("stageReward err:", err)
	}
	return ret
}

// return is first time and countdown
func checkCountdown(userID int) (bool, int) {
	var first = false
	var countdown = RESET_COUNTDOWN

	f, _ := global.GetRds().Exists(fmt.Sprintf(RESET_STAGE, userID)).Result()

	log.Println("f:", f)

	if f == 0 {
		first = true
	}

	if !first {
		c, _ := global.GetRds().Get(fmt.Sprintf(RESET_STAGE, userID)).Int64()
		st, _ := timehelper.INaDay2Unix("")
		divide := int((st - c) / (3600 * 24))

		countdown = countdown - divide

		// 到达重置日期时
		if countdown == 0 {
			first = true
			countdown = RESET_COUNTDOWN
		}
	}
	return first, countdown
}
